# -*- coding: utf-8 -*-
# created on 2016/12/06

from sympy import Union

from mathsolver.functions.base.base import BaseFunction, new_latex
from mathsolver.functions.base.objects import BaseIneq, BaseIneqs, BaseEqs, BaseEq, BaseBelong, BaseSymbolValue
from mathsolver.functions.daoshu.daoshuyunsuan import HanShuDaoShuYunSuan
from mathsolver.functions.fangcheng.budengshi import FangChenBuDengShi001, FangChenBuDengShi002
from mathsolver.functions.hanshu.dandiaoqujian import DiZengQuJian, DiJianQuJian
from mathsolver.functions.hanshu.helper import check_inter, check_func, simplify_budengshi_item
from mathsolver.functions.hanshu.hengchengli import HengChengLiRenYiXing
from mathsolver.functions.root.jiefangchen import JieFangChen
from mathsolver.functions.root.jiefangchenzu import JieFangChenZu


class QuJianZiJiQiuCan(BaseFunction):
    """A ⊆ B, 求参数"""

    def solver(self, *args):
        da, db = check_inter(args[0]), check_inter(args[1])
        ineqs = []
        if not da.left.is_infinite and not db.left.is_infinite:
            ineqs.append([da.left, ">=", db.left])

        if not da.right.is_infinite and not db.right.is_infinite:
            ineqs.append([da.right, "<=", db.right])

        if len(ineqs) > 1:
            stepsolver = FangChenBuDengShi002().solver(BaseIneqs(ineqs))
        else:
            stepsolver = FangChenBuDengShi001().solver(BaseIneq(ineqs[0]))

        self.steps.extend(stepsolver.steps)
        self.output = stepsolver.output
        self.label.add("已知区间是另一区间的子集求参数")
        return self


class QuJianXiangDengQiuCan(BaseFunction):
    """集合相等，求参数"""

    def solver(self, *args):
        da, db = check_inter(args[0]), check_inter(args[1])
        eqs = []
        if not da.left.is_infinite and not db.left.is_infinite:
            eqs.append([da.left, db.left])

        if not da.right.is_infinite and not db.right.is_infinite:
            eqs.append([da.right, db.right])

        if len(eqs) > 1:
            stepsolver = JieFangChenZu().solver(BaseEqs(eqs))
            self.steps.append(["", "解 %s 得：" % BaseEqs(eqs).printing()])
        else:
            stepsolver = JieFangChen().solver(BaseEq(eqs[0]))
            self.steps.append(["", "解 %s 得：" % BaseEq(eqs[0]).printing()])

        self.steps.append([stepsolver.output[0].printing(), ""])
        self.output = stepsolver.output
        self.label.add("已知区间相等求参数")
        return self


class DiZenQuJianQiuCan1(BaseFunction):
    """已知函数的单调递增区间，求参数"""
    hanshu = DiZengQuJian

    def solver(self, *args):
        func, inter = check_func(args[0]), args[1].interval
        dandiao_solver = self.hanshu().solver(func)
        self.steps.extend(dandiao_solver.steps)
        qujian = dandiao_solver.output[0].value
        self.steps.append(["", "由题意知，%s 和 %s 为相同的区间" % (new_latex(inter), new_latex(qujian))])
        qujian_solver = QuJianXiangDengQiuCan().solver(inter, qujian)
        self.steps.extend(qujian_solver.steps)
        self.output = qujian_solver.output
        self.label.add("函数的单调区间求参数")
        return self


class DiZenQuJianQiuCan(BaseFunction):
    """已知函数的单调递增区间，求参数 - 如果区间为 R 尝试 qujian_dizen_qiucan"""

    def solver(self, *args):
        try:
            return DiZenQuJianQiuCan1(self.known).solver(*args)
        except Exception:
            return QuJianDiZenQiuCan(self.known).solver(*args)


class DiJianQuJianQiuCan1(DiZenQuJianQiuCan1):
    """已知函数的单调递减区间，求参数"""
    hanshu = DiJianQuJian


class DiJianQuJianQiuCan(BaseFunction):
    """已知函数的单调递增区间，求参数 -  如果区间为 R 尝试 qujian_dijian_qiucan"""

    def solver(self, *args):
        try:
            return DiJianQuJianQiuCan1(self.known).solver(*args)
        except Exception:
            return QuJianDiJianQiuCan(self.known).solver(*args)


class DiZenQiuCanHengChengLi(BaseFunction):
    """函数在区间上单调递增，求参数 - 恒成立方法"""
    op = ">="

    def solver(self, *args):
        func, inter = check_func(args[0]), check_inter(args[1])
        func_var = func.var

        # 求导
        deriv = HanShuDaoShuYunSuan().solver(func).output[0]
        self.steps.append(["", "对函数求导得 %s" % deriv.printing()])

        # 化简 deriv.expression, 去掉 E**x 和 ()**2，()**(-2) 这类项
        new_expr = simplify_budengshi_item(deriv.expression)

        # 函数在区间上单调性转化成导函数在区间上的不等式关系
        self.steps.append(["", "问题转化为 %s ∈ %s 时， %s %s 0 恒成立" % (new_latex(func_var), new_latex(inter), new_latex(deriv.expression), self.op)])

        renyixing_solver = HengChengLiRenYiXing(self.known).solver(BaseIneq([new_expr, self.op, '0']), BaseBelong([func_var, "\\in", inter]))
        self.steps.extend(renyixing_solver.steps)
        self.output = renyixing_solver.output
        self.label.add("函数在区间上的单调增/减求参数")
        return self


class DiJianQiuCanHengChengLi(DiZenQiuCanHengChengLi):
    """函数在区间上单调，求参数 - 恒成立方法"""
    op = "<="


class QuJianDanDiaoQiuCan(BaseFunction):
    def solver(self, *args):
        symbolvalues = []

        try:
            dizen_solver = QuJianDiZenQiuCan().solver(*args)
        except Exception:
            self.steps.append(["", "由题意知函数在区间上不可能单调递增"])
        else:
            self.steps.append(["", "当函数在区间上单调递增时"])
            self.steps.extend(dizen_solver.steps)
            symbolvalues.append(dizen_solver.output[0].value)

        try:
            dijian_solver = QuJianDiJianQiuCan().solver(*args)
        except Exception:
            self.steps.append(["", "由题意知函数在区间上不可能单调递减"])
        else:
            self.steps.append(["", "当函数在区间上单调递减时"])
            self.steps.extend(dijian_solver.steps)
            symbolvalues.append(dijian_solver.output[0].value)

        canshu = list(symbolvalues[0].keys())[0]

        output_result = Union(*[list(item.values())[0] for item in symbolvalues])

        self.steps.append(["", "所以参数取值范围为：%s ∈ %s" % (new_latex(canshu), new_latex(output_result))])
        self.output.append(BaseSymbolValue({canshu: output_result}))
        self.label.add("函数在区间上单调求参数")
        return self


QuJianDiZenQiuCan = DiZenQiuCanHengChengLi
QuJianDiJianQiuCan = DiJianQiuCanHengChengLi

if __name__ == '__main__':
    pass
